package org.haredot.context;

import org.haredot.web.RequestMapping;
import org.haredot.web.RequestMethod;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 维护 Web应用的上下文
 * 负责 扫描 所有 @Controller 注解的类，并找到 类中包含 @RequestMapping 注解的信息
 */
public class WebApplicationContext implements ApplicationContext{

    private final List<RequestMapping> list = new CopyOnWriteArrayList<>();

    {
        loadRequestMappings();
    }
    /**
     * 读取 所有的请求映射
     * @return
     */
    private void loadRequestMappings() {
        // 从 一级缓存 中 遍历所有的对象
        ONE_CACHE_MAP.values().forEach(obj -> {
            loadMappings(obj.getClass(), list);
        });

        TWO_CACHE_MAP.values().forEach(clz -> {
            loadMappings(clz, list);
        });

    }

    public List<RequestMapping> getRequestMappings() {
        return this.list ;
    }

    private static void loadMappings(Class<?> clz, List<RequestMapping> list) {
        String onePath = "" ;
        // 获取 该对象 类上是否有 @RequestMapping注解
        if (clz.isAnnotationPresent(org.haredot.annotation.RequestMapping.class)) {
            org.haredot.annotation.RequestMapping mapping = clz.getAnnotation(org.haredot.annotation.RequestMapping.class);
            onePath = mapping.value() ;
        }

        // 获取 obj 对象中定义的所有 公开方法中的 RequestMapping 注解
        Method[] methods = clz.getMethods();

        for(Method method : methods) {
            String twoPath = "" ;
            if (method.isAnnotationPresent(org.haredot.annotation.RequestMapping.class)) {
                org.haredot.annotation.RequestMapping annotation = method.getAnnotation(org.haredot.annotation.RequestMapping.class);
                twoPath = annotation.value();
                RequestMethod[] requestMethods = annotation.method();
                RequestMapping requestMapping = new RequestMapping() ;
                requestMapping.setTarget(clz);
                requestMapping.setMethod(method);
                requestMapping.setRequestMethods(Arrays.stream(requestMethods).toList());
                // 将一级 和 二级路径拼接，形成以为 完整路径
                String path = onePath + twoPath ;
                requestMapping.setUrlPattern(path);
                list.add(requestMapping);
            }
        }
    }
}
